/**
 * 实现函数组合
 * @returns 
 */
export function compose(){
    let funcs = Array.from(arguments)

    return function(arg){
        // 方法一：循环
        // let sum = arg
        // while (funcs.length > 0){
        //     const fun = funcs.pop()
        //     sum = fun(sum)
        // }
        // return sum

        // 方法二：reverse、reduce
        return funcs.reverse().reduce((num, func)=>{
            return func(num)
        }, arg)
    }
}

// 测试代码
// function sum1(a){
//     return a+5
// }
// function sum2(a){
//     return a*10
// }

// const c = compose(sum2, sum1)

// console.log(c(2))



/**
 * 使用 setTimeout 实现一个 setInterval
 */
let timer = null

function mySetInterval(fn, time){
    timeInterval()

    return timer

    function timeInterval() {
        timer = setTimeout(()=>{
            fn()
            timeInterval()
        }, time)
    } 
}

function myClear(timer) {
    clearTimeout(timer)
}

// 测试代码
// const myTimer = mySetInterval(()=>{
//     console.log("mySetInterval")
// }, 1000)

// myClear(myTimer)


/**
 * 发布订阅模式；hub改用对象{}可能更好
 */
class EventEmitter {
    constructor(){
        this.hub = []
    }

    subscribe(name, callback) {
        const event = this.hub.find(item => item.name===name)

        if(event){
            event.callback.push(callback)
        }
        else{
            this.hub.push({
                name,
                callback: [callback]
            })
        }
    }

    off(name){
        this.hub = this.hub.filter(item => name!==item.name)
    }

    emit(name) {
        const event = this.hub.find(item => item.name===name)

        if(event){
            event.callback.map(cb => {
                cb()
            })
        }
    }
    once(name, callback){
        const event = this.hub.find(item => item.name===name)

        if(event){
            this.off(name)
        }

        this.hub.push({
            name,
            callback: [callback]
        })
    }
}


// 测试代码
// const hub = new EventEmitter()

// hub.once("click", ()=>{
//     console.log("click1")
// })

// hub.once("click", ()=>{
//     console.log("click2")
// })
// hub.emit("click")

// hub.off("click")

// hub.emit("click")

/**
 * 数组去重，不好的方案
 * @param {*} arr 
 */
// function removeRepeat(arr) {

//     let array = []

//     arr.forEach(element => {
//         let item = JSON.stringify(element)
//         if(array.indexOf(item) < 0){
//             array.push(item)
//         }
//     });

//     return array.map(item=>JSON.parse(item))
// }

/**
 * 数组去重，根据某属性去重
 * @param {*} arr 
 */
function removeRepeat(arr, pro) {

    let obj = {}

    return arr.filter(item => {
        const value = item[pro]
        if(!obj[value]){
            obj[value] = true

            return true
        }

        return false
    })


}

// const arr1 = [
//     {
//         name: "11",
//         age: 10
//     },
//     {
//         name: "11",
//         age: 10
//     },
//     {
//         name: "12",
//         age: 10
//     }
// ]

// console.log(removeRepeat(arr1, "name"))

/**
 * 数组扁平化
 */
function flattern(arr) {
    let array = []

    arr.forEach(item => {
        if(Array.isArray(item)){
            array = array.concat(flattern(item))
        }
        else{
            array.push(item)
        }
    })

    return array
}
// console.log(flattern([1, 2, [1, [2, 3, [4, 5, [6]]]]]))


/**
 * 判断一个对象是否是原型链上的实例
 * @param {*} conFunc 
 * @returns 
 */
Object.prototype.myInstenceOf = function (conFunc){
    let obj = this
    if(typeof conFunc !== "function"){
        return false
    }

    do{
        if(obj.__proto__ === conFunc.prototype){
            return true
        }
        obj = obj.__proto__
    }while(obj != null)

    return false
}


function MyClass (){

}

const obj2 = new MyClass()

const ob3 = {
    Function,
    Object
}

// js原型链关键点：
// 1、对象都有__proto__属性，且js先查找本身属性再才查找__proto__里面的属性；
// 2、函数才有prototype
// 3、每个实例对象的__proto__都指向构造函数的prototype，所以可以共用构造函数的prototype
// 4、如何实现继承，例如：

// obj2 => MyClass => Function
// console.log(obj2)
// console.log(MyClass)
// console.log(MyClass.__proto__ === Function.prototype) // true
// console.log(Object.__proto__ === Function.prototype) // true
// console.log(Function.__proto__ === Object) // false
// console.log("Function.__proto__:", Function.__proto__)

// console.log("ob3:", ob3)
// console.log("Object.__proto__:", Object.__proto__)
// console.log("Object.prototype:", Object.prototype)

// // 测试代码
// console.log(obj2.myInstenceOf(MyClass))
// console.log(ob3.myInstenceOf(MyClass))



